package net.qiqbframework.tracing;

import net.qiqbframework.messaging.Message;

import java.util.function.Supplier;

/**
 * 负责 SpanFactory 使 spans 所选的跟踪提供程序兼容。
 * 每个跨度都有一个操作名称和跨度类型。从操作名称中，应该清楚地知道应用程序中发生了什么。例如，用于 "ClassName. method MessageName" 指示正在处理的消息有效负载。
 * 跨度可以有标签，这些标签由 SpanAttributesProviders提供。默认情况下，在创建跨度时，每次使用消息时，都应调用所有配置 SpanAttributesProviders 的跨度，并在创建的跨度上设置这些标记。
 * 工厂应支持以下类型的跨度：
 * 新的根跟踪跨度：这些跨度会创建一个没有父级的全新跟踪。对于我们想要单独测量性能的异步调用，请使用此选项。例如，快照（对业务流程没有影响）。
 * 新处理程序跨度：这将在已存在的跟踪中创建一个新跨度。发送消息时处于活动状态的跨度将链接到该跨度。它将是处理类型
 * 新调度跨度：这将在已存在的跟踪中创建新跨度。它将是调度类型。
 * 新的内部跨度：这将在已激活的跨度中创建一个新的子跨度。使用它来测量已经存在的跨度的各个部分。例如，测量在处理事件时加载聚合所需的时间。
 */
public interface SpanFactory {

    Span createRootTrace(Supplier<String> operationNameSupplier);


    default Span createLinkedHandlerSpan(Supplier<String> operationNameSupplier, Message<?> parentMessage, Message<?>... linkedParents) {
        return createHandlerSpan(operationNameSupplier, parentMessage, false, linkedParents);
    }


    default Span createChildHandlerSpan(Supplier<String> operationNameSupplier, Message<?> parentMessage, Message<?>... linkedParents) {
        return createHandlerSpan(operationNameSupplier, parentMessage, true, linkedParents);
    }

    Span createHandlerSpan(Supplier<String> operationNameSupplier, Message<?> parentMessage, boolean isChildTrace,
                           Message<?>... linkedParents);

    Span createDispatchSpan(Supplier<String> operationNameSupplier, Message<?> parentMessage, Message<?>... linkedSiblings);


    Span createInternalSpan(Supplier<String> operationNameSupplier);


    Span createInternalSpan(Supplier<String> operationNameSupplier, Message<?> message);


    void registerSpanAttributeProvider(SpanAttributesProvider provider);

    <M extends Message<?>> M propagateContext(M message);
}
